using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace Pronghorn.Core
{
	public abstract class FilesTagBase : IRenderable
	{
		protected string _code;
		protected readonly Uri _pathToFile;

		protected FilesTagBase(string code)
		{
			_code = code;
		}

		protected FilesTagBase(Uri pathToFile)
		{
			_pathToFile = pathToFile;
		}

		protected string ScriptType
		{
			get; set;
		}

		public List<string> Code
		{
			get
			{
				if (String.IsNullOrEmpty(_code))
				{
					return GetLinesOfCodeFromFile();
				}
				return GetLinesOfCodeFromCode(_code);
			}
		}

		protected List<string> GetLinesOfCodeFromCode(string code)
		{
			return new List<string>(code.Split(new []{"\r\n"}, StringSplitOptions.RemoveEmptyEntries));
		}

		protected List<string> GetLinesOfCodeFromFile()
		{
			var path = GetUriPath();
			var lines = new List<string>();

			if (_pathToFile == null || string.IsNullOrEmpty(path) || !File.Exists(path))
			{
			    return lines;

			}
			
			using (var streamReader = new StreamReader(path))
			{
				string line;
				while ((line = streamReader.ReadLine()) != null)
				{
					lines.Add(line);
				}
			}

			return lines;
		}

		public virtual string GetUniqueKey()
		{
			var md5 = new MD5CryptoServiceProvider();
			var bytes = Encoding.UTF8.GetBytes(Code[0]);
			var hashArray = md5.ComputeHash(bytes);
			var result = hashArray.Select(h => h.ToString("x2")).Aggregate((hash, h) => hash + h);
			return result;
		}

		public string GetUriPath()
		{
			if (_pathToFile == null) return string.Empty;
			if (_pathToFile.IsAbsoluteUri) return _pathToFile.AbsolutePath;
		    string basePath;
		    try
		    {
                basePath = HttpRuntime.AppDomainAppPath;

		    }
		    catch (Exception)
		    {
                return Path.GetFullPath(_pathToFile.ToString());
		    }
            return basePath + VirtualPathUtility.ToAbsolute("~/" + _pathToFile);
		}

		public virtual void Render(TextWriter writer)
		{
			if (_code != null)
			{
				RenderInlineTag(writer);
			}
			else if (_pathToFile != null)
			{
				RenderTagFromFile(writer);
			}
		}

		protected abstract void RenderTagFromFile(TextWriter writer);

		protected abstract void RenderInlineTag(TextWriter writer);
	}
}